<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>18.多图型扫光</title>
</head>
<body>
	<canvas id="canvas" style="background-color: #000000;"></canvas>
	<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/primitives.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/texture-utils.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/chroma.min.js"></script>
	<script type="x-shader/x-vertex" id="vertex">
		attribute vec4 a_position;
		attribute vec3 a_normal;
		uniform mat4 u_projection;
		uniform vec3 u_lightWorldPosition;
		uniform vec3 u_lightWorldPosition2;
		uniform mat4 u_view;
		uniform mat4 u_world;
		varying vec3 v_normal;
		
		varying vec3 v_surfaceToLight;
		varying vec3 v_surfaceToLight2;
		varying vec3 v_surfaceToView;
		varying vec3 iPosition;
		void main(){
			gl_Position =  u_projection * u_view * u_world * a_position;
			//gl_Position.xyz/=1.02;
			iPosition=a_position.xyz;
			v_normal=(u_world*vec4(a_normal,1.)).xyz;
			v_surfaceToView=(u_world*vec4(a_position)).xyz;
			v_surfaceToLight=(vec4(u_lightWorldPosition-v_surfaceToView,1)).xyz;
			v_surfaceToLight2=(vec4(u_lightWorldPosition2-v_surfaceToView,1)).xyz;
		}
	</script>
	<script type="x-shader/x-fragment" id="fragment">
		precision mediump float;
		uniform vec3 u_color;
		uniform float u_time;
		varying vec3 v_normal;
		uniform float u_innerLimit;          // in dot space
		uniform float u_outerLimit;          // in dot space
		varying vec3 v_surfaceToLight;
		varying vec3 v_surfaceToView;
		varying vec3 v_surfaceToLight2;
		varying vec3 iPosition;
		void main(){
			gl_FragColor = vec4(u_color, 1.0 ) ;
		}
	</script>
	<script type="x-shader/x-vertex" id="vertex2">
		attribute vec4 a_position;
		attribute vec3 a_normal;
		uniform mat4 u_projection;
		uniform vec3 u_lightWorldPosition;
		uniform vec3 u_lightWorldPosition2;
		uniform mat4 u_view;
		uniform mat4 u_world;
		varying vec3 v_normal;
		
		varying vec3 v_surfaceToLight;
		varying vec3 v_surfaceToLight2;
		varying vec3 v_surfaceToView;
		varying vec3 iPosition;
		attribute vec2 a_texcoord;
		
		varying vec2 v_texCoord;
		void main(){
			gl_Position =  a_position;
			//gl_Position.xyz/=1.02;
			iPosition=a_position.xyz;
			v_normal=(u_world*vec4(a_normal,1.)).xyz;
			v_surfaceToView=(u_world*vec4(a_position)).xyz;
			v_surfaceToLight=(vec4(u_lightWorldPosition-v_surfaceToView,1)).xyz;
			v_surfaceToLight2=(vec4(u_lightWorldPosition2-v_surfaceToView,1)).xyz;
			v_texCoord=a_texcoord;
		}
	</script>
	<script type="x-shader/x-fragment" id="fragment2">
		precision mediump float;
		uniform vec3 u_color;
		uniform float u_time;
		varying vec3 v_normal;
		uniform float u_innerLimit;          // in dot space
		uniform float u_outerLimit;          // in dot space
		varying vec3 v_surfaceToLight;
		varying vec3 v_surfaceToView;
		varying vec3 v_surfaceToLight2;
		varying vec3 iPosition;

		
		varying vec2 v_texCoord;
		uniform sampler2D u_texture;
		void main(){
			gl_FragColor = vec4(u_color, 1.0 ) ;
			
			vec4 diffuseColor = texture2D(u_texture, v_texCoord);//纹理
			gl_FragColor = diffuseColor;
			

			float x = iPosition.x-u_time;//x
			gl_FragColor = gl_FragColor ;
			float y = iPosition.y;
			  // 一粗一细两束光线
			if ((y < -x && y > -x - 0.1)){
				gl_FragColor = mix(gl_FragColor, vec4(1.0), 0.5);
			}
			gl_FragColor = diffuseColor;
			float inLight = smoothstep( u_outerLimit, u_innerLimit,dot(normalize(v_surfaceToView),-normalize(v_surfaceToLight)));//Hermite 插值
			
			float light = inLight * dot(normalize(v_normal), normalize(v_surfaceToView));
			gl_FragColor.rgb*=light;
			float d=dot(normalize(v_surfaceToView),-normalize(v_surfaceToLight));
			float d2=dot(normalize(v_surfaceToView),-normalize(v_surfaceToLight2));
			gl_FragColor = diffuseColor ;
			if(d2<u_innerLimit&&d2>u_outerLimit&&d<u_outerLimit){
				gl_FragColor = mix(gl_FragColor, vec4(1.0), 0.5);
			}
			
			gl_FragColor = diffuseColor;
            float lighty = -x*1.2+u_time;//-x*1.2+time
            float alpha = abs(iPosition.y - lighty);//y-lighty
            if(alpha < 0.1){
				if(diffuseColor.a>0.){
					float a = 1.0  -  alpha / .1;
					float enda = smoothstep(0.0,1.0,a) + 0.3;
					gl_FragColor = mix(diffuseColor, vec4(1.0), 0.5);
					gl_FragColor = diffuseColor * enda;
				}else{
					gl_FragColor = mix(gl_FragColor, vec4(1.0), 0.5);
				}
            }else{
                gl_FragColor = gl_FragColor * 0.15;
            }

		}
	</script>
	<script>
		const canvas = document.getElementById("canvas");
		
		const width=canvas.width=window.innerWidth
		const height=canvas.height=window.innerHeight
		const gl = canvas.getContext("webgl")
		const aspect = gl.canvas.clientWidth/ gl.canvas.clientHeight;
		const programInfo=webglUtils.createProgramInfo(gl,["vertex","fragment"])
		const programInfo2=webglUtils.createProgramInfo(gl,["vertex2","fragment2"])
		const cubBufferInfo = primitives.createCubeBufferInfo(
			gl,
			30
		);
		const planeBufferInfo = primitives.createPlaneBufferInfo(
			gl,
			width,  // width
			height,  // height
			1,   // subdivisions across
			1,   // subdivisions down
		);
		
		const quadBufferInfo = primitives.createXYQuadBufferInfo(gl);
		// const planeBufferInfo = primitives.createSphereBufferInfo(
		// 	gl,
		// 	20,  // radius
		// 	50, // subdivisions around
		// 	50,  // subdivisions down
		// );
		const cameraMatrix = m4.lookAt([0,140,150],[0,0,0],[0,1,0])
		const viewMatrix=m4.inverse(cameraMatrix)
		
		const cameraMatrix2 = m4.lookAt([0,0,1],[0,0,0],[0,1,0])
		const viewMatrix2=m4.inverse(cameraMatrix2)
		function degToRad(d) {
			return d * Math.PI / 180;
		}
		
		var cameraPosition = [0, 0, 4];
		var world=m4.translation(0, 0, 0)
		let t=1
		let limit=60
		let innerLimit=0
		let outerLimit=60
		let time=-1

		function rand(min, max) {
			return Math.random() * (max - min) + min;
		}

		const obj=[

		]
		const projectionMatrix=m4.perspective(degToRad(60), aspect, 1, 2000);

		for (let index = 0; index < 50; index++) {
			
			const object={
				u_view: viewMatrix,					//视图
				u_projection: projectionMatrix,		//投影
				u_world:null,	//世界
				translation:[rand(-width/2,width/2),rand(-height/2,height/2),rand(0,-height/2)],
				u_lightWorldPosition:[200,-400,0],
				u_lightWorldPosition2:[100,-200,0],
				u_color:[rand(0,1),rand(0,1),rand(0,1)],
				u_outerLimit:Math.cos(degToRad(outerLimit)),
				u_innerLimit:Math.cos(degToRad(innerLimit)),
				u_time:time,
			}

			obj.push(object)
		}
		gl.enable(gl.CULL_FACE);
		gl.enable(gl.DEPTH_TEST);
		const targetTexture = gl.createTexture();
		gl.bindTexture(gl.TEXTURE_2D,targetTexture)
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,width, height, 0,gl.RGBA, gl.UNSIGNED_BYTE, null);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		//创建帧缓存区
		//绑定帧缓存区
		//附加纹理
		const fb = gl.createFramebuffer();
		gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
		gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, targetTexture, 0);

		//创建渲深度缓冲区并绑定
		//初始化渲染对象存储
		//附加到帧缓存区
		const depthBuffer = gl.createRenderbuffer();
		gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
		gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
		gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, gl.canvas.width, gl.canvas.height);
		gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
		setInterval(()=>{

			if(innerLimit>=100){
				t=-0.1
			}
			if(innerLimit<=0){
				t=0.1
			}
			innerLimit+=t
			outerLimit+=t
			time+=.001
			if(time>1){
				time=-1
			}
			gl.useProgram(programInfo.program)
			//world = m4.yRotate(world, 0.001)
			// webglUtils.setUniforms(programInfo, {
			// 	u_view: viewMatrix,					//视图
			// 	u_projection: projectionMatrix,		//投影
			// 	u_world:world,	//世界
			// 	u_lightWorldPosition:[200,-400,0],
			// 	u_lightWorldPosition2:[100,-200,0],
			// 	u_color:[0.5,0.5,0.5],
			// 	u_outerLimit:Math.cos(degToRad(outerLimit)),
			// 	u_innerLimit:Math.cos(degToRad(innerLimit)),
			// 	u_time:time,
			// });
			// webglUtils.drawBufferInfo(gl, planeBufferInfo);

			gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
		gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
			obj.forEach(o=>{
				o.u_world=m4.translation(...o.translation)
				webglUtils.setBuffersAndAttributes(gl, programInfo, cubBufferInfo);
				webglUtils.setUniforms(programInfo, o);
				webglUtils.drawBufferInfo(gl, cubBufferInfo);
			})
			gl.useProgram(programInfo2.program)

				webglUtils.setBuffersAndAttributes(gl, programInfo2, quadBufferInfo);
				webglUtils.setUniforms(programInfo2, {
					u_view: viewMatrix2,					//视图
					u_projection: projectionMatrix,		//投影
					u_world:world,	//世界
					u_lightWorldPosition:[200,-400,0],
					u_lightWorldPosition2:[100,-200,0],
					u_color:[0.5,0.5,0.5],
					u_outerLimit:Math.cos(degToRad(outerLimit)),
					u_innerLimit:Math.cos(degToRad(innerLimit)),
					u_time:time,
				});
				gl.bindFramebuffer(gl.FRAMEBUFFER, null);
				gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
				gl.bindTexture(gl.TEXTURE_2D, targetTexture);
				webglUtils.drawBufferInfo(gl, quadBufferInfo);
			
		},0)
		/*
			扫光

			外圈，内圈之间的有光照，其他地方不影响

		*/
	</script>
</body>
</html>